package com.hnu.seckill.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hnu.seckill.entity.SeckillInfo;
import com.hnu.seckill.entity.TOrder;
import com.hnu.seckill.entity.TSeckillOrder;
import com.hnu.seckill.entity.TUser;
import com.hnu.seckill.rabbitmq.MQSender;
import com.hnu.seckill.service.ITGoodsService;
import com.hnu.seckill.service.ITOrderService;
import com.hnu.seckill.service.ITSeckillOrderService;
import com.hnu.seckill.utils.JsonUtil;
import com.hnu.seckill.vo.GoodsVo;
import com.hnu.seckill.vo.RespBean;
import com.hnu.seckill.vo.RespBeanEnum;
import org.apache.ibatis.annotations.Insert;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Controller
@RequestMapping("/seckill")
public class SecKillController implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> list = goodsService.findGoodsVo();
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.forEach(goodsVo -> {
            redisTemplate.opsForValue().
                    set("seckillGoods:" + goodsVo.getId(), goodsVo.getStockCount());
            map.put(goodsVo.getId(), false);
        });
    }

    @Autowired
    private ITGoodsService goodsService;

    @Autowired
    private ITSeckillOrderService seckillOrderService;

    @Autowired
    private ITOrderService orderService;
    @Qualifier("redisTemplate")
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MQSender mqSender;

    @Autowired
    private RedisScript<Long> redisScript;

    private Map<Long, Boolean> map = new ConcurrentHashMap<>();

    /**
     * windows 优化前QPS 1498.7/sec    100000 times
     *
     * @param model
     * @param user
     * @param goodsId
     * @return
     */
    @RequestMapping("/doSeckill")
    public String doSeckill(Model model, TUser user, Long goodsId) {
        if (user == null) {
            return "login";
        }


        ValueOperations valueOperations = redisTemplate.opsForValue();
        TSeckillOrder seckillOrder = (TSeckillOrder) redisTemplate.opsForValue().get("order:" + user.getId() + ":" + goodsId);
        if (seckillOrder != null) {
            model.addAttribute("errmsg", RespBeanEnum.REPEAT_ERROR.getMsg());
            return "secKillFail";
        }
        if (map.get(goodsId)) {
            model.addAttribute("errmsg", RespBeanEnum.EMPTY_STOCK.getMsg());
            return "secKillFail";
        }
//        Long stock = valueOperations.decrement("seckillGoods:" + goodsId);
        Long stock = (Long) redisTemplate.execute(redisScript, Collections.singletonList("seckillGoods:" + goodsId), Collections.EMPTY_LIST);
        if (stock < 0) {
            valueOperations.increment("seckillGoods:" + goodsId);
            model.addAttribute("errmsg", RespBeanEnum.EMPTY_STOCK.getMsg());
            map.put(goodsId, true);
            return "secKillFail";
        }
        SeckillInfo seckillInfo = new SeckillInfo(user, goodsId);
        mqSender.sendSeckillMessage(JsonUtil.object2JsonStr(seckillInfo));
        model.addAttribute(0);

        return "orderDetail";

//        GoodsVo goodsVo = goodsService.findGoodsVobyGoodsId(goodsId);
//        if(goodsVo.getStockCount()<1){
//            model.addAttribute("errmsg", RespBeanEnum.EMPTY_STOCK.getMsg());
//            return "secKillFail";
//        }
//        //判断是否重复抢购
////        TSeckillOrder seckillOrder = seckillOrderService.getOne(new QueryWrapper<TSeckillOrder>()
////                .eq("user_id", user.getId())
////                .eq("goods_id", goodsId));
//        TSeckillOrder seckillOrder = (TSeckillOrder) redisTemplate.opsForValue().get("order:" + user.getId() + ":" + goodsId);
//        if(seckillOrder!=null){
//            model.addAttribute("errmsg", RespBeanEnum.REPEAT_ERROR.getMsg());
//            return "secKillFail";
//        }
//        TOrder tOrder = orderService.secKill(user, goodsVo);
//        model.addAttribute("order", tOrder);
//        model.addAttribute("goods",goodsVo);
//
//        return "orderDetail";
    }
}
